<html>
<head>
  <title>Evernote Export</title>
  <basefont face="微软雅黑" size="2" />
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <meta name="exporter-version" content="YXBJ Windows/600753 (zh-CN, DDL); Windows/10.0.0 (Win64);"/>
  <style>
    body, td {
      font-family: 微软雅黑;
      font-size: 10pt;
    }
  </style>
</head>
<body>
<a name="1362"/>

<div>
<span><div><h1 style="outline: 0px; margin: 0.67em 0px; padding: 0px; font-size: 24px; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; overflow-wrap: break-word; color: rgba(0, 0, 0, 0.75); font-variant-ligatures: common-ligatures; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="color: rgb(77, 77, 77); font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; font-size: 12px; font-variant-ligatures: common-ligatures; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);">本文链接：</span><a href="https://blog.csdn.net/lk3030/article/details/84108765" style="outline: 0px; color: rgb(51, 153, 234); cursor: pointer; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; overflow-wrap: break-word; font-size: 14px; font-variant-ligatures: common-ligatures; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">https://blog.csdn.net/lk3030/article/details/84108765</a><br/></h1><h1 style="outline: 0px; margin: 0.67em 0px; padding: 0px; font-size: 24px; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; overflow-wrap: break-word; color: rgba(0, 0, 0, 0.75); font-variant-ligatures: common-ligatures; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);"><span style="outline: 0px; font-size: 24px; font-family: &quot;Microsoft YaHei&quot;, &quot;SF Pro Display&quot;, Roboto, Noto, Arial, &quot;PingFang SC&quot;, sans-serif; overflow-wrap: break-word; color: rgba(0, 0, 0, 0.75); font-variant-ligatures: common-ligatures; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">MeanShift 目标跟踪</span></h1><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">MeanShift 原理</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">MeanShift的本质是一个迭代的过程，在一组数据的密度分布中，使用无参密度估计寻找到局部极值（不需要事先知道样本数据的概率密度分布函数，完全依靠对样本点的计算）。</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">在d维空间中，任选一个点，然后以这个点为圆心，h为半径做一个高维球，因为有d维，d可能大于2，所以是高维球。落在这个球内的所有点和圆心都会产生一个向量，向量是以圆心为起点落在球内的点位终点。然后把这些向量都相加。相加的结果就是下图中黄色箭头表示的MeanShift向量：</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">  </span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">然后，再以这个MeanShift 向量的终点为圆心，继续上述过程，又可以得到一个MeanShift 向量：</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">不断地重复这样的过程，可以得到一系列连续的MeanShift 向量，这些向量首尾相连，最终可以收敛到概率密度最大得地方（一个点）：</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">从上述的过程可以看出，MeanShift 算法的过程就是：从起点开始，一步步到达样本特征点的密度中心。</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">MeanShift 跟踪步骤</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">1.获取待跟踪对象</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">获取初始目标框（RoI）位置信息（x,y,w,h），截取 RoI图像区域</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 初始化RoI位置信息</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">track_window = (c,r,w,h)</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 截取图片RoI</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">roi = img[r:r+h, c:c+w]</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">2.转换颜色空间</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">将BGR格式的RoI图像转换为HSV格式，对 HSV格式的图像进行滤波，去除低亮度和低饱和度的部分。</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">在 HSV 颜色空间中要比在 BGR 空间中更容易表示一个特定颜色。在 OpenCV 的 HSV 格式中，H（色度）的取值范围是 [0，179]， S（饱和度）的取值范围 [0，255]，V（亮度）的取值范围 [0，255]。</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 转换到HSV</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 设定滤波的阀值</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">lower = np.array([0.,130.,32.])</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">upper = np.array([180.,255.,255.])</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 根据阀值构建掩模</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">mask = cv2.inRange(hsv,lower, upper)</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">3.获取色调统计直方图</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 获取色调直方图</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">roi_hist = cv2.calcHist([hsv_roi],[0],mask,[180],[0,180])</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 直方图归一化</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">cv2.normalize(roi_hist,roi_hist,0,180,cv2.NORM_MINMAX)</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">cv2.calcHist的原型为：</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]])  </span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">1</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">images: 待统计的图像，必须用方括号括起来，</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">channels：用于计算直方图的通道，这里使用色度通道</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">mask：滤波掩模</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">histSize：表示这个直方图分成多少份（即多少个直方柱）</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">ranges：表示直方图中各个像素的值的范围</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">4.在新的一帧中寻找跟踪对象</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 读入目标图片</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">ret, frame = cap.read()</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 转换到HSV</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 获取目标图片的反向投影</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 定义迭代终止条件</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"># 计算得到迭代次数和目标位置</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">ret, track_window = cv2.meanShift(dst, track_window, term_crit)</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">meanShift 函数原型</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">def meanShift(probImage, window, criteria)</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">1</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">probImage：输入反向投影直方图</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">window：需要移动的矩形（ROI）</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">criteria：对meanshift迭代过程进行控制的初始参量</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">其中，criteria参数如下：</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">type：判定迭代终止的条件类型：</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">COUNT：按最大迭代次数作为求解结束标志</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">EPS：按达到某个收敛的阈值作为求解结束标志</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">COUNT + EPS：两个条件达到一个就算结束</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">maxCount：具体的最大迭代的次数</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">epsilon：具体epsilon的收敛阈值</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">反向投影</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;">反向投影图输出的是一张概率密度图，与输入图像大小相同，每一个像素值代表了输入图像上对应点属于目标对象的概率，像素点越亮，代表这个点属于目标物体的概率越大。</span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div><div><span style="font-size: 18pt; color: rgba(0, 0, 0, 0.75); font-family: &quot;Microsoft YaHei&quot;;"><br/></span></div></div></span>
</div></body></html> 